using System;
using System.Globalization;
using GammaJul.ReSharper.GammaXaml.Highlightings.CSharp;
using GammaJul.ReSharper.GammaXaml.Psi;
using JetBrains.Annotations;
using JetBrains.Application.Progress;
using JetBrains.ProjectModel;
using JetBrains.ReSharper.Feature.Services.Bulbs;
using JetBrains.ReSharper.Intentions.Extensibility;
using JetBrains.ReSharper.Intentions.Util;
using JetBrains.ReSharper.Psi;
using JetBrains.ReSharper.Psi.CSharp.Tree;
using JetBrains.ReSharper.Psi.Util;
using JetBrains.ReSharper.Psi.Xaml.Impl.Resolve;
using JetBrains.TextControl;
using JetBrains.Util;

namespace GammaJul.ReSharper.GammaXaml.QuickFixes.CSharp {

	/// <summary>
	/// Quick fix that makes a class inherit from DependencyObject.
	/// </summary>
	[QuickFix]
	public sealed class InheritFromDependencyObjectFix : QuickFixBase {
		private readonly OwnerMustBeDependencyObjectHighlighting _highlighting;

		public override string Text {
			get {
				return String.Format(
					CultureInfo.CurrentCulture,
					"Make '{0}' inherit from 'DependencyObject'",
					_highlighting.OwnerClass != null ? _highlighting.OwnerClass.ShortName : "???");
			}
		}

		protected override Action<ITextControl> ExecutePsiTransaction(ISolution solution, IProgressIndicator progress) {
			IClass ownerClass = _highlighting.OwnerClass;
			Assertion.Assert(ownerClass != null, "ownerClass != null");

			var declaration = ownerClass.GetDeclarations().FirstInNonGeneratedFileOrFallback() as IClassDeclaration;
			if (declaration != null)
				declaration.SetSuperClass(XamlTypeCache.GetCache(ownerClass.Module).DependencyObject);

			return null;
		}

		/// <summary>
		/// This quick fix is available on classes that are declared in source code and that derive from object.
		/// </summary>
		/// <param name="cache">A cache.</param>
		/// <returns><c>true</c> if the quick fix is available, <c>false</c> otherwise.</returns>
		public override bool IsAvailable(IUserDataHolder cache) {
			IClass ownerClass = _highlighting.OwnerClass;
			return ownerClass != null
				&& _highlighting.IsValid()
				&& ValidUtils.Valid(ownerClass, true)
				&& ownerClass.GetSuperClass().IsObjectClass();
		}

		public InheritFromDependencyObjectFix([NotNull] OwnerMustBeDependencyObjectHighlighting highlighting) {
			if (highlighting == null)
				throw new ArgumentNullException("highlighting");
			_highlighting = highlighting;
		}
	}
}
